package com.yunhan.scc.article.utils.execlutil;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

import com.yunhan.scc.article.web.entities.masterdata.EduMasterdataMarkeinfoDO;

public class ExeclReadUtil {
	private HSSFWorkbook wb;

	public  InputStream readFileAsStream(String path) throws IOException{
		if(path == null){
			return null;
		}else{
			File file = new File(path);
			return readFileAsStream(file);
		}
	}
	
	public  InputStream readFileAsStream(File file) throws IOException{
		if(!file.exists()){
			return null;
		}
		if(file.isFile() && file.canRead()){
			return new FileInputStream(file);
		}else{
			return null;
		}
	}
	/**
	 * main 方法用于测试，和演示使用
	 * @author YangTao 2016年1月31日 上午11:49:24
	 * @param args
	 * @return void
	 */
	public static void main(String[] args) {
		ExeclReadUtil execlRead = new ExeclReadUtil();
		InputStream is;
		try {
			//实体类，演示用法
			//Persion persion = new Persion();
			EduMasterdataMarkeinfoDO eduMasterdataMarkeinfoDO = new EduMasterdataMarkeinfoDO();
			//默认处理Execlhandle 演示使用
			DefaultHandleExecl defaultHandleExecl = new DefaultHandleExecl();
			is = execlRead.readFileAsStream("D:/上传.xls");
			if(is == null){
				return;
			}
			Out_Parameter_Total out_Parameter_Total = new Out_Parameter_Total(0);
			execlRead.readDate(is, eduMasterdataMarkeinfoDO, defaultHandleExecl, ColORRow.ROW, 0, out_Parameter_Total);
		}  catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	/**
	 * 读取Execl文件函数入口，由于Execl数据的多样性，我们这里提供按行读取和按列读取的方式。行读取的话，就是行中包含bean的属性。
	 * 列读取的方式是第一行表示bean的属性。
	 * <h2>特别注意:Execl 中有我们看不到的字符（就是空值），这个空值找不到。这可能导致我们读取Execl失败。</h2>
	 * @author YangTao 2016年2月14日 上午9:08:37
	 * @param is 输入流
	 * @param bean Execl对应实体类
	 * @param handleData 处理数据接口
	 * @param colORRow 枚举，表示如何处理这个Execl，是按照行读还是按照列读。
	 * @param startPos 读取的开始位置。 开始位置为下标，和Execl中的不一样，下标从0开始。
	 * @param rows 需要读取多少行。 传入0 表示从开始位置读取到结尾哦
	 * @return List<String> 返回错误数据
	 * @throws Exception 
	 */
	public List<ExeclBeanInterface> readDate(InputStream is,ExeclBeanInterface bean,ExeclHandleData handleData,ColORRow colORRow,int startPos,Out_Parameter_Total rows) throws Exception{
		if(colORRow == ColORRow.COLUMN){
			return readColumnData(is,bean,handleData,startPos,rows);
		}else{
			return readRowData(is,bean,handleData,startPos,rows);
		}
	}
	
	private List<ExeclBeanInterface> readColumnData(InputStream is,ExeclBeanInterface bean,ExeclHandleData handleData,int startPos,Out_Parameter_Total rows) throws Exception{
		return readColumnExcelContent(is,bean,handleData,startPos,rows);
	}
	
	public List<ExeclBeanInterface> readColumnData (InputStream is,ExeclBeanInterface bean,ExeclHandleData handleData) throws Exception{
		Out_Parameter_Total out_Parameter_Total = new Out_Parameter_Total(0);
		return readColumnData(is,bean,handleData,0,out_Parameter_Total);
	}
	
	/**
	 * 默认是从开始读取到文件结尾。
	 * @author YangTao 2016年2月14日 上午11:06:52
	 * @param is 输入流
	 * @param bean 对应实体类
	 * @param handleData 自己实现处理数据接口
	 * @return List<String> 返回的错误数据
	 * @throws Exception 
	 */
	public List<ExeclBeanInterface> readRowData(InputStream is,ExeclBeanInterface bean,ExeclHandleData handleData) throws Exception{
		Out_Parameter_Total out_Parameter_Total = new Out_Parameter_Total(0);
		return readRowData(is,bean,handleData,0,out_Parameter_Total);
	}
	
	public List<ExeclBeanInterface> readRowData(InputStream is,ExeclBeanInterface bean,ExeclHandleData handleData,int startPos,Out_Parameter_Total rows) throws Exception{
		return readRowExcelContent(is,bean,handleData,startPos,rows);
	}
	

	/**
	 * 
	 * @author YangTao 2016年1月29日 上午10:01:09
	 * @param is 输入流
	 * @param handleData 处理数据接口 {@link ExeclHandleData}
	 * @return void
	 * @throws Exception 
	 */
    private List<ExeclBeanInterface> readRowExcelContent(InputStream is,ExeclBeanInterface bean,ExeclHandleData handleData,int startPos,Out_Parameter_Total out_rows) throws Exception {
    	//用于记录返回结果
    	List<ExeclBeanInterface> list = new ArrayList<ExeclBeanInterface>();
    	POIFSFileSystem fs;
		
		fs = new POIFSFileSystem(is);
		wb = new HSSFWorkbook(fs);;
		
        HSSFSheet sheet = wb.getSheetAt(0);

    	HashMap<Integer, String> titleMap = new HashMap<>();
    	StringBuilder result = new StringBuilder();
        // 得到总行数 用于计算需要读取的位置
        int rowNum = sheet.getLastRowNum();
        HSSFRow row = sheet.getRow(startPos);
        int colNum = row.getLastCellNum();
        
      //获取Execl标题
    	for(int i = 0 ; i < colNum; i++){
    		titleMap.put(i, row.getCell(i).getRichStringCellValue().getString());
    	}
    	int rows = out_rows.getTotal();
    	
    	if(rows == 0){//传入0的话，表示全部读取。
    		rowNum = rowNum - startPos;//即 从开始位置到最后
    	}else{
    		 rowNum = startPos + rows;//即 从开始位置 + 要读取的行数。
    	}
    	out_rows.setTotal(rowNum);
    	startPos++;
    	
        for (;startPos <= rowNum; startPos++) {
        	
            row = sheet.getRow(startPos);
            result.append("{");
            for(int cellPos = 0; cellPos < colNum; cellPos++){
            	
            	String titleName = titleMap.get(cellPos);
            	String beanPortiesName = bean.getPerties(titleName);
            	
            	result.append("\"").append(beanPortiesName).append("\"").
            	append(":").append(getCellFormatValue(row.getCell(cellPos))).append(",");
            	
            }
            result.deleteCharAt(result.length() - 1).append("}");
            System.out.println(result.toString());
            //这里我们可以对数据进行处理了，比如转成bean，插入数据库等操作。这里我们使用接口处理，自己要实现的业务逻辑实现接口就行了
            ExeclBeanInterface initbean = JsonToBeanUtil.jsonToBean(result.toString(), bean.getClass());

            initbean = handleData.handleData(initbean,bean);
            if(initbean.hasError()){
            	
            	list.add(initbean);
            }
            result.delete(0, result.length());
        }
        //最后关闭文件流
        StreamUtils.closeInStream(is);
        return list;
    }
     /**
      * 
      * @author YangTao 2016年2月14日 下午12:15:58
      * @param is 输入流
      * @param bean Execl对应实体类
      * @param handleData 处理接口
      * @param startPos 开始位置
      * @param rows 需要读取多少行 0 ，表示全部读取
      * @return List<String> 错误数据汇总
     * @throws Exception 
      */
    private List<ExeclBeanInterface> readColumnExcelContent(InputStream is,ExeclBeanInterface bean,ExeclHandleData handleData,int startPos,Out_Parameter_Total out_rows) throws Exception{
    	//用于记录返回结果
    	List<ExeclBeanInterface> list = new ArrayList<ExeclBeanInterface>();
    	POIFSFileSystem fs;
		
		fs = new POIFSFileSystem(is);
		wb = new HSSFWorkbook(fs);;
		
        HSSFSheet sheet = wb.getSheetAt(0);

//    	HashMap<Integer, String> titleMap = new HashMap<>();
    	StringBuilder result = new StringBuilder();
        // 得到总行数 用于计算需要读取的位置
        int rowNum = sheet.getLastRowNum();
        HSSFRow row = sheet.getRow(startPos);
        int colNum = row.getLastCellNum();
        int rows = out_rows.getTotal();
    	if(rows == 0){//传入0的话，表示全部读取。
    		rowNum = rowNum - startPos;//即 从开始位置到最后
    	}else{
    		 rowNum = startPos + rows;//即 从开始位置 + 要读取的行数。
    	}
    	out_rows.setTotal(rowNum);
        for (;startPos <= rowNum; startPos++) {
        	
            row = sheet.getRow(startPos);
            result.append("{");
            for(int cellPos = 0; cellPos < colNum; cellPos++){
            	
            	String titleName = getCellFormatValue(row.getCell(cellPos));
            	String beanPortiesName = bean.getPerties(titleName.replace("\"", ""));
            	
            	if(beanPortiesName == null || beanPortiesName.equals("")){
            		result.append(titleName).append(",");
            	}else{
            		result.append(beanPortiesName).append(":");
            	}
            }
            result.deleteCharAt(result.length() - 1).append("}");
            System.out.println(result.toString());
            //这里我们可以对数据进行处理了，比如转成bean，插入数据库等操作。这里我们使用接口处理，自己要实现的业务逻辑实现接口就行了
            ExeclBeanInterface initbean = JsonToBeanUtil.jsonToBean(result.toString(), bean.getClass());
            
            initbean = handleData.handleData(initbean,bean);
            
            if(initbean.hasError()){
            	list.add(initbean);
            }

            result.delete(0, result.length());
        }
        //最后关闭文件流
        StreamUtils.closeInStream(is);
        return list;
    }
    
    private String getCellFormatValue(HSSFCell cell) {
        String cellvalue = "";
        if (cell != null) {
            switch (cell.getCellType()) {
            case HSSFCell.CELL_TYPE_STRING:
                // 取得当前的Cell字符串 由于我们转成字符JSON形式的字符串，我们在字符串上面加上引号
                cellvalue = "\"" + cell.getRichStringCellValue().getString() + "\"";
                break;
            case HSSFCell.CELL_TYPE_BLANK:
            	cellvalue = "\"\"";
            	break;
            case HSSFCell.CELL_TYPE_NUMERIC:
            	cellvalue = String.valueOf(cell.getNumericCellValue());
            	break;
            	
            case HSSFCell.CELL_TYPE_FORMULA: {
                // 判断当前的cell是否为Date
                if (HSSFDateUtil.isCellDateFormatted(cell)) {
                    // 如果是Date类型则，转化为Data格式
                    
                    //方法1：这样子的data格式是带时分秒的：2011-10-12 0:00:00
                    //cellvalue = cell.getDateCellValue().toLocaleString();
                    
                    //方法2：这样子的data格式是不带带时分秒的：2011-10-12
                    Date date = cell.getDateCellValue();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    cellvalue = sdf.format(date);
                    
                }
                // 如果是纯数字
                else {
                    // 取得当前Cell的数值
                    cellvalue = String.valueOf(cell.getNumericCellValue());
                }
                break;
            }
            
            // 默认的Cell值
            default:
                cellvalue = "";
            }
        } else {
            cellvalue = "";
        }
        return cellvalue;

    }
    

}
